<template>
  <div
    class="side-box"
    ref="sideBox"
    :class="{ hiddenBar: hidden }"
    v-show="sideBarVisible"
    @mouseleave="barMouseLeave"
    @contextmenu.prevent.stop
  >
    <div
      class="side-container w-[52px] h-full flex flex-col justify-between items-center rounded-[16px] py-[8px] ml-2.5 bg-black/40"
    >
      <div class="side-box__header">
        <img
          class="h-[36px] w-[36px] rounded-[10px] cursor-pointer"
          :src="avatar"
          alt="头像"
          @click="clickAvatar"
        />
      </div>
      <div class="group relative w-full flex-grow" @wheel.stop="onWheel">
        <div
          class="wrapper absolute top-0 bottom-0 overflow-hidden w-[150px]"
          ref="sideWrapper"
        >
          <div
            ref="sideContent"
            class="side-box__content flex flex-col gap-[8px] grow shrink-0 py-[16px] pl-[8px]"
          >
            <div
              v-for="(item, index) in list"
              :ref="(el) => setRef(el, `dom${item.id}`)"
              :key="item.id"
              draggable="true"
              class="side-box__item w-[36px] h-[36px] rounded-[8px] p-1 flex items-center hover:bg-white/15 cursor-pointer"
              :class="activeIndex === index ? 'bg-white/15 ' : ''"
              @click="changeTab(index)"
              @contextmenu.stop.prevent="showContextMenu(item, $event)"
            >
              <div class="relative">
                <span
                  class="side-box__icon iconfont"
                  v-if="!item.iconClass?.includes('/')"
                  :class="
                    (activeIndex === index
                      ? ' text-white '
                      : 'text-white/60 ') + `icon-${item.iconClass}`
                  "
                ></span>
                <img
                  v-else
                  class="icongroup-img w-[28px] h-[28px]"
                  :alt="item.name"
                  :src="item.iconClass"
                  :class="{ checked: activeIndex === index }"
                />
                <div
                  class="side-box__tip opacity-0 pr-[8px] ppl-[4px] font-ali-65 text-white pointer-events-none absolute inline-flex h-[24px] max-w-[80px] items-center rounded-[4px] text-[12px] left-[50px] top-[5px]"
                >
                  <span class="overflow">{{ item.name }}</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="side-box__add relative">
        <div
          class="h-[36px] w-[36px] shrink-0 cursor-pointer rounded-[8px] p-[4px] text-[rgba(255,255,255,0.6)] transition-colors hover:bg-[rgba(0,0,0,0.15)]"
        >
          <section
            class="h-full bg-current"
            style="
              mask-image: url('');
            "
            @click="addHandler()"
          ></section>
        </div>
      </div>
    </div>
    <div
      class="w-[60px] h-full absolute right-[-150px] top-0"
      v-if="sideBarAuto"
      :class="{ hideHolder: !hidden }"
      @mouseenter="holderDomMouseEnter"
    ></div>
    <Teleport to="#app">
      <IconMenu
        class="side-box__menu z-sideBarIcons"
        v-show="showIcons"
        ref="iconMenu"
        :style="menuPos"
        :cate="cate"
        :saveType="cate.id ? 'edit' : 'add'"
        @addOrEditCategory="addOrEditCategory"
      ></IconMenu>
    </Teleport>
  </div>
</template>
<script setup lang="ts">
import {
  ref,
  onMounted,
  reactive,
  watchEffect,
  watch,
  inject,
  computed,
} from 'vue';
import Sortable from 'sortablejs';
import { onClickOutside } from '@vueuse/core';
import {
  useUserInfoStore,
  useSettingStore,
  useContextMenuStore,
  useIconListStore,
} from '../store';
import { ElMessage, ElMessageBox } from 'element-plus';
import IconMenu from '../elements/IconMenu.vue';
import categoryApi from '../api/category';
import type { Cate } from '../api/category';

const userInfoStore = useUserInfoStore();
const settingStore = useSettingStore();
const contextMenuStore = useContextMenuStore();
const iconListStore = useIconListStore();

const sideContent = ref(null);
const dynamicRefs = ref({});

const setRef = (el, name) => {
  dynamicRefs[name] = el;
};

const list = ref<Cate[]>([]);
const cate = ref<Cate>({ name: '', iconClass: '' });

const avatar = computed(() => {
  return settingStore.setting.avatar || userInfoStore.userInfo.avatar;
});
const sideBarVisible = computed(() => {
  const { theSidebar } = settingStore.setting;
  return settingStore.setting.theSidebar ? theSidebar !== 'never' : true;
});

const sideBarAuto = computed(() => {
  return settingStore.setting.theSidebar === 'auto';
});
const hidden = ref(false);
watchEffect(() => {
  if (settingStore.setting.theSidebar === 'auto') {
    hidden.value = true;
  } else {
    hidden.value = false;
  }
});

function holderDomMouseEnter() {
  hidden.value = false;
}

function barMouseLeave() {
  if (!sideBarAuto.value) {
    return;
  }
  if (showIcons.value) {
    return;
  }
  const selectMenu = document.querySelector('.select-menu');
  if (selectMenu) {
    return;
  }
  hidden.value = true;
}

const menuItems = ref([]);
function showContextMenu(item, event) {
  // 隐藏列表
  showIcons.value = false;
  menuItems.value = [
    { label: '编辑', value: 'editGroup' },
    { label: '删除', value: 'deleteGroup' },
  ];
  contextMenuStore.setTarget(item);
  contextMenuStore.setContextMenu(menuItems.value);
  if (dynamicRefs[`dom${item.id}`]) {
    const { top, left } = dynamicRefs[`dom${item.id}`].getBoundingClientRect();
    contextMenuStore.setPosition({
      clientX: left + 48,
      clientY: top + 36,
    });
  } else {
    contextMenuStore.setPosition({
      clientX: event.clientX,
      clientY: event.clientY,
    });
  }
}

// 点击编辑分类
const editHandler = (item) => {
  const { id } = item;
  if (dynamicRefs[`dom${id}`]) {
    const { top, left, width } =
      dynamicRefs[`dom${id}`].getBoundingClientRect();
    menuPos.value = {
      top: `${top}px`,
      left: left + width + 12 + 'px',
      bottom: 'auto',
    };
    dynamicRefs[`dom${id}`].classList.add('editing');
  }
  cate.value = item;
  showIcons.value = true;
};

const deleteHandler = (id) => {
  const index = list.value.findIndex((item) => item.id === id);
  let delId = undefined;
  if (index === activeIndex.value) {
    delId = index;
  }
  categoryApi.delete([{ id }]).then(() => {
    getCategories(delId);
  });
};

watchEffect(() => {
  if (contextMenuStore.menuActive === 'editGroup') {
    editHandler(contextMenuStore.target);
    contextMenuStore.setMenuActive('');
  } else if (contextMenuStore.menuActive === 'deleteGroup') {
    // 判断是否是主页
    if (contextMenuStore.target.name === '主页') {
      ElMessage({
        message: '主页不可删除',
        type: 'warning',
      });
      contextMenuStore.setMenuActive('');
      return;
    }
    // 判断是否有图标
    if (iconListStore.iconList?.length > 0) {
      ElMessageBox.confirm(
        '删除分类将同时删除分类下的所有图标和小组件。',
        '提醒',
        {
          confirmButtonText: '删除',
          cancelButtonText: '取消',
          type: 'warning',
        }
      )
        .then(() => {
          deleteHandler(contextMenuStore.target.id);
          contextMenuStore.setMenuActive('');
        })
        .catch(() => {
          contextMenuStore.setMenuActive('');
        });
    } else {
      deleteHandler(contextMenuStore.target.id);
      contextMenuStore.setMenuActive('');
    }
  }
});

const updateCate = (data) => {
  emits('update:currentCate', data);
};
// 获取分类列表
const getCategories = (index = undefined) => {
  return new Promise<void>((resolve) => {
    categoryApi.get().then((res) => {
      console.log(res,'---------------------------------------')
      list.value = res;
      contextMenuStore.setMenuList(res);
      const { length } = list.value;
      if (index !== undefined && length) {
        if (index >= length) {
          index = length - 1;
        }
        changeTab(index);
      }
      resolve();
    });
  });
};
getCategories().then(() => {
  if (list.value && list.value.length > 0) {
    updateCate(list.value[0].id);
  }
});

const activeIndex = defineModel<number>('activeIndex');
const props = defineProps(['activeIndex']);
const emits = defineEmits([
  'update:activeIndex',
  'update:currentCate',
  'clickAvatar',
]);

watch(
  () => activeIndex.value,
  (newValue, oldValue) => {
    updateCate(list.value[props.activeIndex].id);
  }
);

const clickAvatar = () => {
  emits('clickAvatar');
};

const menuPos = ref({});
const showIcons = ref(false);

// 配置点击外部关闭
const iconMenu = ref<HTMLElement | null>(null);
onClickOutside(iconMenu, () => {
  showIcons.value = false;
});

watchEffect(() => {
  if (!showIcons.value) {
    if (cate.value.id) {
      dynamicRefs[`dom${cate.value.id}`].classList.remove('editing');
    }
    cate.value = { name: '', iconClass: '' };
  }
});

// 点击添加分类
const sideBox = ref<HTMLElement | null>(null);
const addHandler = () => {
  if (sideBox.value) {
    const { left, width, bottom } = sideBox.value.getBoundingClientRect();
    menuPos.value = {
      bottom: innerHeight - bottom + 'px',
      left: left + width + 4 + 'px',
      top: 'auto',
    };
  }
  showIcons.value = true;
};

const showCategory = (style) => {
  showIcons.value = true;
  for (const key in style) {
    menuPos.value[key] = `${style[key]}px`;
  }
};

const addOrEditCategory = (item: Cate) => {
  if (item.id) {
    // 编辑
    categoryApi.edit(item).then((res) => {
      getCategories();
    });
  } else {
    // 调接口
    // item.id = list.value.length + 1;
    if (item.name === '主页') {
      if (list.value.find((i) => i.name === '主页')) {
        ElMessage({
          message: '主页不可重复',
          type: 'warning',
        });
        return;
      }
    }
    // 设置排序
    item.orderSotr =  (list.value[list.value.length - 1]?.orderSotr ? list.value[list.value.length - 1].orderSotr + 1 : 1);
    categoryApi.add(item).then(() => {
      getCategories().then((res) => {
        // 切换到该分类
        changeTab(list.value.length - 1);
        sideContent.value.scrollTop = sideContent.value.scrollHeight;
      });
    });
  }
  // 关闭菜单
  showIcons.value = false;
};

const getTotalLength = () => {
  return list.value.length;
};

defineExpose({
  getTotalLength,
});

onMounted(() => {
  const sortable = Sortable.create(sideContent.value, {
    animation: 300,

    onEnd: function (/**Event*/ evt) {
      if (evt.newIndex === evt.oldIndex) {
        return;
      }
      const currentCate = list.value[activeIndex.value];
      // 将拖拽的元素插入到新的位置
      const [movedItem] = list.value.splice(evt.oldIndex, 1);
      list.value.splice(evt.newIndex, 0, movedItem);
      activeIndex.value = list.value.findIndex(
        (item) => item.id === currentCate.id
      );
    },
  });
});

const sideWrapper = ref<HTMLElement | null>(null);
const sideItem = ref<HTMLElement[] | null>(null);
let obj = null;
function getDimensions() {
  const itemHeight = 36;
  const parentHeight = sideWrapper.value.offsetHeight;
  const listHeight = (itemHeight + 8) * list.value.length + 24;
  obj = { itemHeight, parentHeight, listHeight };

  return obj;
}
let translateY = 0;
function updateTranslateY(newTranslateY) {
  const { parentHeight, listHeight } = getDimensions();
  translateY = Math.min(0, Math.max(newTranslateY, parentHeight - listHeight));

  sideContent.value.style.transform = `translateY(${translateY}px)`;
}

const changeTab = (index: number) => {
  emits('update:activeIndex', index);
  updateCate(list.value[index]?.id);

  const { parentHeight, itemHeight } = getDimensions();
  const targetTranslateY = -(
    index * (itemHeight + 8) -
    (parentHeight / 2 - (itemHeight + 8) / 2)
  );
  updateTranslateY(targetTranslateY);
};

function onWheel(event) {
  const { itemHeight } = getDimensions();
  event.preventDefault();
  const delta = event.deltaY;

  if (delta > 0) {
    // Scroll down
    updateTranslateY(translateY - itemHeight);
  } else {
    // Scroll up
    updateTranslateY(translateY + itemHeight);
  }
}
</script>
<style scoped lang="scss">
.side-box {
  height: clamp(min(480px, 70%), 636px, 70%);
  transition: all 0.3s;

  &.hiddenBar {
    transform: translate(-160px, -50%);
  }
}

.hideHolder {
  display: none;
}
.side-container {
  backdrop-filter: saturate(200%) blur(40px);
}
.side-box__tip {
  transition: all 0.2s;
}

.side-box__content {
  transition: transform 0.2s;
}
.side-box__content:hover .side-box__tip {
  opacity: 1;
}

.side-box__item {
  -webkit-user-drag: element;
}
.side-box__item:hover .side-box__tip {
  background-color: white;
  color: #000;
  padding: 0 8px;
}
.side-box__header::after,
.side-box__add::before {
  content: '';
  width: 22px;
  height: 2px;
  background-color: rgba(0, 0, 0, 0.2);
  display: block;
  margin: 0 auto;
}
.side-box__header::after {
  margin-top: 22px;
}
.side-box__add::before {
  margin-bottom: 22px;
}
.side-box__icon {
  font-size: 24px;
  width: 28px;
  height: 28px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.side-box__menu {
  left: 66px;
}

.icongroup-img {
  position: relative;
  left: -300px;
  filter: drop-shadow(300px 0 var(--btn-color-active, rgb(255 255 255 / 0.6)));
  &.checked {
    filter: drop-shadow(300px 0 var(--btn-color-active, #fff));
  }
}

.editing {
  background-color: #ffffff26;

  .icongroup-img {
    filter: drop-shadow(300px 0 var(--btn-color-active, #4a7aff));
  }
  .side-box__icon {
    color: #4a7aff;
  }
}
</style>
<!-- <style>
.side-box__content:hover .side-box__tip {
  opacity: 1;
}
</style> -->
